package com.xtm.exercise.utils.export;

import com.github.junrar.Archive;
import com.github.junrar.rarfile.FileHeader;
import com.one.common.utils.easyexcel.EasyExcelUtil;
import com.one.common.utils.easyexcel.model.EasyExcelImportResult;
import com.one.common.utils.service.IEasyExcelImportService;
import jxl.Sheet;
import jxl.Workbook;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public final class ExcelImportUtil {

	/**
	 * 解析 Excel，并储存
	 */
	private static void saveExcelFiles(List<File> excelFiles, ExcelImportsService service,
			Map<String, Object> paramsMap) throws Exception {

		for (File excelFile : excelFiles) {

			Workbook workbook = null;
			InputStream is = null;
			try {
				is = new FileInputStream(excelFile.getPath());
				workbook = Workbook.getWorkbook(is);

				List<List<String[]>> excelData = new ArrayList<>();

				Sheet[] sheets = workbook.getSheets();

//				for (Sheet sheet : sheets) {
					Sheet sheet = sheets[0];
					List<String[]> list = new ArrayList<>();

					int columns = sheet.getColumns();
					int rows = sheet.getRows();

					for (int i = 1; i < rows; i++) {

						String[] line = new String[columns];
                        if(StringUtils.isEmpty(sheet.getCell(0, i).getContents())){
                        	break;
                        }
						for (int j = 0; j < columns; j++) {
							line[j] = sheet.getCell(j, i).getContents();
						}
						list.add(line);
					}
					excelData.add(list);
//				}

				service.checkExcelData(excelData, paramsMap);
			} finally {
				if (workbook != null) {
					workbook.close();
				}
				if (is != null) {
					is.close();
				}
			}

			service.saveExcelData(paramsMap);
		}
	}
	
	/**
	 * 解析 Excel，并储存 ,针对多表头
	 */
	private static void saveGroupExcelFiles(List<File> excelFiles, ExcelImportsService service,
			Map<String, Object> paramsMap) throws Exception {

		for (File excelFile : excelFiles) {

			Workbook workbook = null;
			InputStream is = null;
			try {
				is = new FileInputStream(excelFile.getPath());
				workbook = Workbook.getWorkbook(is);

				List<List<String[]>> excelData = new ArrayList<>();

				Sheet[] sheets = workbook.getSheets();

//				for (Sheet sheet : sheets) {
					Sheet sheet = sheets[0];
					List<String[]> list = new ArrayList<>();

					int columns = sheet.getColumns();
					int rows = sheet.getRows();

					for (int i = 3; i < rows; i++) {

						String[] line = new String[columns];
                        if(StringUtils.isEmpty(sheet.getCell(0, i).getContents())){
                        	break;
                        }
						for (int j = 0; j < columns; j++) {
							line[j] = sheet.getCell(j, i).getContents();
						}
						list.add(line);
					}
					excelData.add(list);
//				}

				service.checkExcelData(excelData, paramsMap);
			} finally {
				if (workbook != null) {
					workbook.close();
				}
				if (is != null) {
					is.close();
				}
			}

			service.saveExcelData(paramsMap);
		}
	}


	/**
	 * 解压 rar文件到指定文件夹
	 */
	private static void unrar(List<File> rarFiles, String savedFolder) throws Exception {

		for (File rarFile : rarFiles) {
			Archive archive = null;
			try {
				archive = new Archive(new FileInputStream(rarFile));

				FileHeader fileHeader = archive.nextFileHeader();
				while (fileHeader != null) {
					if (fileHeader.isDirectory()) {
						fileHeader = archive.nextFileHeader();
						continue;
					}

					String fileName = fileHeader.getFileNameW().isEmpty() ? fileHeader.getFileNameString()
							: fileHeader.getFileNameW();

					File out = new File(savedFolder + fileName);
					if (!out.exists()) {
						if (!out.getParentFile().exists()) {
							out.getParentFile().mkdirs();
						}
						out.createNewFile();
					}
					FileOutputStream os = null;
					try {
						os = new FileOutputStream(out);
						archive.extractFile(fileHeader, os);
					} catch (Exception e) {
						if (os != null) {
							os.close();
						}
					}
					fileHeader = archive.nextFileHeader();
				}
			} finally {
				if (archive != null) {
					archive.close();
				}
			}
		}
	}

	private static void unzip(List<File> zipFiles, String savedFolder) throws Exception {

		Charset charset = Charset.forName("GBK");

		ZIP_FILE: for (int i = 0, len = zipFiles.size(); i < len; i++) {
			ZipFile zipFile = null;
			try {
				File zipName = zipFiles.get(i);
				zipFile = new ZipFile(zipName, charset);
				Enumeration<? extends ZipEntry> entries = zipFile.entries();
				while (entries.hasMoreElements()) {
					ZipEntry zipEntry = null;
					try {
						zipEntry = entries.nextElement();
					} catch (IllegalArgumentException e) {
						// 因为不确定压缩包是用那种方式进行压缩的
						// 所以默认用GBK解压，出错了就再用 UTF-8 去解压
						// 如果两个都出错的时候，判断压缩包损坏
						if (e.getMessage().equals("MALFORMED") && charset == StandardCharsets.UTF_8) {
							throw new Exception("压缩包损坏");
						}
						i--;
						charset = StandardCharsets.UTF_8;
						continue ZIP_FILE;
					}

					String fileName = zipEntry.getName();

					File temp = new File(savedFolder + fileName);

					if (!zipEntry.isDirectory()) {// 非目录才进行写入

						OutputStream os = null;
						InputStream is = null;
						try {
							os = new FileOutputStream(temp);
							// 通过ZipFile的getInputStream方法拿到具体的ZipEntry的输入流
							is = zipFile.getInputStream(zipEntry);
							int isLen = 0;
							while ((isLen = is.read()) != -1) {
								os.write(isLen);
							}
						} finally {
							if (os != null) {
								os.close();
							}
							if (is != null) {
								is.close();
							}
						}
					} else {
						if (!temp.exists()) {
							temp.mkdir();
						}
					}
				}
			} finally {
				zipFile.close();
			}
		}
	}

	public static Map<String, Object> uploadInit(HttpServletRequest request/*, BaseController controller*/) {

		Map<String, Object> paramsMap = new HashMap<String, Object>();
//		UvmpUser loginUser = controller.getLoginUser();
//		paramsMap.put("loginUser", loginUser);

		String authToken = request.getHeader("Authorization");
		paramsMap.put("Authorization", authToken);

		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
		Iterator<String> fileNames = multipartRequest.getFileNames();
		List<MultipartFile> multipartFiles = new ArrayList<>();
		while (fileNames.hasNext()) {
			multipartFiles.add(multipartRequest.getFile(fileNames.next()));
		}

		paramsMap.put("multipartFiles", multipartFiles);

		return paramsMap;

	}

	/**
	 * poi导入
	 * @param service
	 * @param paramsMap
	 * @param module
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static void saveData(ExcelImportsService service, Map<String, Object> paramsMap, String module)
			throws Exception {

		Map<String, List<File>> files = null;
		try {

			List<MultipartFile> multipartFiles = (List<MultipartFile>) paramsMap.get("multipartFiles");

			files = ExcelUploadUtil.upload(multipartFiles, module);

			String savedFolder = ExcelUploadUtil.getSavePath() + "/" + module + "/";
			paramsMap.put("savedFolder", savedFolder);

			if (files.containsKey(ExcelUploadUtil.XLS_FILE)) {
				saveExcelFiles(files.get(ExcelUploadUtil.XLS_FILE), service, paramsMap); // 处理excel文件
			}
			if (files.containsKey(ExcelUploadUtil.XLSX_FILE)) {
				saveExcelFiles(files.get(ExcelUploadUtil.XLSX_FILE), service, paramsMap); // 处理excel文件
			}

			// unrar(files.get(ExcelUploadUtil.RAR_FILE), savedFolder); // 处理
			// rar 包
			// unzip(files.get(ExcelUploadUtil.ZIP_FILE), savedFolder); // 处理
			// zip包
			if (files.containsKey(ExcelUploadUtil.JPG_FILE)) {
				service.saveImgFiles(files.get(ExcelUploadUtil.JPG_FILE), paramsMap);
			}
			if (files.containsKey(ExcelUploadUtil.PNG_FILE)) {
				service.saveImgFiles(files.get(ExcelUploadUtil.PNG_FILE), paramsMap);
			}
			if (files.containsKey(ExcelUploadUtil.BMP_FILE)) {
				service.saveImgFiles(files.get(ExcelUploadUtil.BMP_FILE), paramsMap);
			}

		} finally {
			if (files != null) {
				ExcelUploadUtil.removeTmpFile(files); // 清理可能未被处理的临时文件
			}
		}
	}



	@SuppressWarnings("unchecked")
	public static EasyExcelImportResult saveDataUseEasyExcel(IEasyExcelImportService easyExcelImportService , Map<String, Object> paramsMap , Class importModelClass , AsyncTaskExecutor asyncTaskExecutor , HttpServletResponse resp , Integer... headRowNumber)
			throws Exception {

		Map<String, List<File>> files = null;
		EasyExcelImportResult easyExcelImportResult = new EasyExcelImportResult();
		try {

			List<MultipartFile> multipartFiles = (List<MultipartFile>) paramsMap.get("multipartFiles");

//			files = ExcelUploadUtil.upload(multipartFiles, module);

/*			String savedFolder = ExcelUploadUtil.getSavePath() + "/" + module + "/";
			paramsMap.put("savedFolder", savedFolder);*/

			if(!ObjectUtils.isEmpty(multipartFiles)){
				for(MultipartFile multipartFile :multipartFiles){
					InputStream inputStream = multipartFile.getInputStream();
					paramsMap.put("fileName" , multipartFile.getOriginalFilename());
					easyExcelImportResult = EasyExcelUtil.readFromExcel(inputStream , importModelClass , easyExcelImportService , paramsMap , asyncTaskExecutor , headRowNumber);
				}
				/*multipartFiles.forEach(multipartFile -> {
					try {
						InputStream inputStream = multipartFile.getInputStream();
						result = EasyExcelUtil.readFromExcel(inputStream , importModelClass , easyExcelImportService , paramsMap , asyncTaskExecutor , headRowNumber);
					} catch (IOException e) {
						logger.error("Get InputStream Error : {}" , ExceptionUtils.getFullStackTrace(e));
					}
				});*/

				if(!easyExcelImportResult.getImportSuccess()){
					StringBuffer errInfo = new StringBuffer("数据校验完成，共" + easyExcelImportResult.getTotalNum() + "行数据，校验成功" + easyExcelImportResult.getSuccessNum() + "行数据。<br/>错误详情：<br/>");
					easyExcelImportResult.getFailedList().forEach(failedResult -> errInfo.append("第" + failedResult.getRowNum() + "行：").append(failedResult.getErrorMessage()).append("<br/>"));
					resp.setStatus(999);
					throw new ImportValidateErrException(errInfo.toString());
				}else{
					if(easyExcelImportResult.getTotalNum() - easyExcelImportResult.getSuccessNum() != 0){
						StringBuffer errInfo = new StringBuffer("共" + easyExcelImportResult.getTotalNum() + "行数据，导入成功" + easyExcelImportResult.getSuccessNum() + "行数据");
						resp.setStatus(999);
						throw new ImportValidateErrException(errInfo.toString());
					}
				}
				/*if(!ObjectUtils.isEmpty(easyExcelImportResult.getFailedList())){
					StringBuffer errInfo = new StringBuffer("共计" + easyExcelImportResult.getTotalNum() + "条数据，导入成功" + easyExcelImportResult.getSuccessNum() + "条数据，错误详情：\r\n");
					easyExcelImportResult.getFailedList().forEach(failedResult -> errInfo.append("第" + failedResult.getRowNum() + "行：").append(failedResult.getErrorMessage()).append("\r\n"));
					resp.setStatus(999);
					throw new ImportValidateErrException(errInfo.toString());
				}*/
			}
			return easyExcelImportResult;
			/*			if (files.containsKey(ExcelUploadUtil.XLS_FILE)) {
				saveExcelFiles(files.get(ExcelUploadUtil.XLS_FILE), service, paramsMap); // 处理excel文件
			}
			if (files.containsKey(ExcelUploadUtil.XLSX_FILE)) {
				saveExcelFiles(files.get(ExcelUploadUtil.XLSX_FILE), service, paramsMap); // 处理excel文件
			}*/

			// unrar(files.get(ExcelUploadUtil.RAR_FILE), savedFolder); // 处理
			// rar 包
			// unzip(files.get(ExcelUploadUtil.ZIP_FILE), savedFolder); // 处理
			// zip包
/*			if (files.containsKey(ExcelUploadUtil.JPG_FILE)) {
				service.saveImgFiles(files.get(ExcelUploadUtil.JPG_FILE), paramsMap);
			}
			if (files.containsKey(ExcelUploadUtil.PNG_FILE)) {
				service.saveImgFiles(files.get(ExcelUploadUtil.PNG_FILE), paramsMap);
			}
			if (files.containsKey(ExcelUploadUtil.BMP_FILE)) {
				service.saveImgFiles(files.get(ExcelUploadUtil.BMP_FILE), paramsMap);
			}*/

		} /*catch (Exception e){
			return easyExcelImportResult;
		}*/finally {
			/*if (files != null) {
				ExcelUploadUtil.removeTmpFile(files); // 清理可能未被处理的临时文件
			}*/
		}
	}

	@SuppressWarnings("unchecked")
	public static void saveGroupData(ExcelImportsService service, Map<String, Object> paramsMap, String module)
			throws Exception {

		Map<String, List<File>> files = null;
		try {

			List<MultipartFile> multipartFiles = (List<MultipartFile>) paramsMap.get("multipartFiles");

			files = ExcelUploadUtil.upload(multipartFiles, module);

			String savedFolder = ExcelUploadUtil.getSavePath() + "/" + module + "/";
			paramsMap.put("savedFolder", savedFolder);

			if (files.containsKey(ExcelUploadUtil.XLS_FILE)) {
				saveGroupExcelFiles(files.get(ExcelUploadUtil.XLS_FILE), service, paramsMap);
			}

			// unrar(files.get(ExcelUploadUtil.RAR_FILE), savedFolder); // 处理
			// rar 包
			// unzip(files.get(ExcelUploadUtil.ZIP_FILE), savedFolder); // 处理
			// zip包
			if (files.containsKey(ExcelUploadUtil.JPG_FILE)) {
				service.saveImgFiles(files.get(ExcelUploadUtil.JPG_FILE), paramsMap);
			}
			if (files.containsKey(ExcelUploadUtil.PNG_FILE)) {
				service.saveImgFiles(files.get(ExcelUploadUtil.PNG_FILE), paramsMap);
			}
			if (files.containsKey(ExcelUploadUtil.BMP_FILE)) {
				service.saveImgFiles(files.get(ExcelUploadUtil.BMP_FILE), paramsMap);
			}

		} finally {
			if (files != null) {
				ExcelUploadUtil.removeTmpFile(files); // 清理可能未被处理的临时文件
			}
		}
	}
}
